package com.lightboat.common.utils;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.gavaghan.geodesy.Ellipsoid;
import org.gavaghan.geodesy.GeodeticCalculator;
import org.gavaghan.geodesy.GeodeticCurve;
import org.gavaghan.geodesy.GlobalCoordinates;

import java.math.BigDecimal;
import java.math.RoundingMode;

@Slf4j
public class DistanceUtils {
    /**
     * 根据经纬度计算距离
     *
     * @param flg  true km(两位小数)，false m(三位小数)
     * @param lon1 经度1
     * @param lat1 纬度1
     * @param lon2 经度2
     * @param lat2 纬度2
     * @return 距离 （km/m）
     */
    public static BigDecimal getDistance(String lon1, String lat1, String lon2, String lat2, boolean flg) {
        GlobalCoordinates source = new GlobalCoordinates(Double.parseDouble(lat1), Double.parseDouble(lon1));
        GlobalCoordinates target = new GlobalCoordinates(Double.parseDouble(lat2), Double.parseDouble(lon2));
        GeodeticCurve geoCurve = new GeodeticCalculator().calculateGeodeticCurve(Ellipsoid.Sphere, source, target);
        double distance = geoCurve.getEllipsoidalDistance();
        if (flg) {
            BigDecimal distanceBig = new BigDecimal(distance).setScale(2, RoundingMode.UP);
            return distanceBig.multiply(new BigDecimal("0.001")).setScale(2, RoundingMode.UP);
        } else {
            return new BigDecimal(distance).setScale(3, RoundingMode.UP);
        }
    }

    /**
     * 假设地球为一半径为R的表面光滑圆球体，
     * 表面上同一经线圈上相差1"两点间的距离为 2πR/360/3600
     * 表面上同一纬线圈上相差1"两点间的距离为 2πR×cos(纬度)/360/3600
     * <p>
     * 当R取半径平均值6371km时，
     * 地球表面上同一经线圈上相差1"两点间的距离约为30.887m
     * 地球表面上同一纬线圈上相差1"两点间的距离约为30.887m×cos(纬度)
     *
     * @param centerLatitude  中心维度
     * @param centerLongitude 中心经度
     * @param radius          半径距离 单位米
     */
    public static range calculateLl(double centerLongitude, double centerLatitude, Double radius) {

        // 地球周长
        Double perimeter = 2 * Math.PI * 6371000;
        // 纬度latitude的地球周长：centerLatitude
        Double perimeter_latitude = perimeter * Math.cos(Math.PI * centerLatitude / 180);

        // 一米对应的经度（东西方向）1M实际度
        double longitude_per_mi = 360 / perimeter_latitude;
        double latitude_per_mi = 360 / perimeter;
        log.debug("经度（东西方向）1M实际度==" + longitude_per_mi);
        log.debug("纬度（南北方向）1M实际度==" + latitude_per_mi);

        Double leftLo = centerLongitude - (radius * longitude_per_mi);  // 左边经度
        Double rightLo = centerLongitude + (radius * longitude_per_mi); // 右边经度
        Double topLa = centerLatitude + (radius * latitude_per_mi);     // 上边经度
        Double bottomLa = centerLatitude - (radius * latitude_per_mi);  // 下边经度

        log.debug("左边经度=" + leftLo);
        log.debug("右边经度" + rightLo);
        log.debug("上边经度" + topLa);
        log.debug("下边经度" + bottomLa);

        return new range(
                new BigDecimal(leftLo).setScale(12, RoundingMode.HALF_UP),
                new BigDecimal(topLa).setScale(12, RoundingMode.HALF_UP),
                new BigDecimal(rightLo).setScale(12, RoundingMode.HALF_UP),
                new BigDecimal(bottomLa).setScale(12, RoundingMode.HALF_UP)
        );
    }

    public static void main(String[] args) {
        String lon1 = "119.6438888888889";
        String lat1 = "37.966944444444444";
        String lon2 = "119.63916666666667";
        String lat2 = "37.9675";
        System.out.println(getDistance(lon1, lat1, lon2, lat2, false));
        System.out.println(getDistance(lon1, lat1, lon2, lat2, true));

        // 中心点是深圳市，半径一公里
        calculateLl(114.057939, 22.543527, 1000D);
    }

    /**
     * 坐上 右下
     */
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public static class range {
        private BigDecimal leftLng;
        private BigDecimal topLat;
        private BigDecimal rightLng;
        private BigDecimal bottomLat;
    }

}